package com.aurora.service.impl.mqtt;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.aurora.config.MqttConfig;
import com.aurora.config.MqttGateway;
import com.aurora.entity.MessageInfo;
import com.aurora.model.dto.UserInfoDTO;
import com.aurora.model.vo.Result;
import com.aurora.model.vo.rabbitMQ.MqttBody;
import com.aurora.service.MessageInfoService;
import com.aurora.service.MqttService;
import com.aurora.service.UserInfoService;
import com.aurora.utils.UserUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))

public class MqttServiceImpl implements MqttService {

    /**
     * 引入Mqtt网关服务
     */
    private final MqttGateway mqttGateway;

    /**
     * 引入消息服务
     */
    private final MessageInfoService messageInfoService;

    /**
     * 引入MQTT配置文件
     */
    private final MqttConfig mqttConfig;

    /**
     * 引入用户信息服务
     */
    private final UserInfoService userInfoService;

    /**
     * 发送消息
     *
     * @param mqttBody 消息体
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> sendMessage(MqttBody mqttBody) {
        //如果消息体包含主题 执行聊天室发送方法 否则执行对话发送方法
        if (StringUtils.isNotBlank(mqttBody.getTopic())) {
            sendToTopic(mqttBody);
        } else {
            sendToDefaultTopic(mqttBody);
        }
        return Result.ok();
    }

    //聊天室发送方法
    public void sendToDefaultTopic(MqttBody mqttBody) {
        //使用BeanUtils工具类将mqttBody转换为MessageInfo对象 并 保存消息到数据库
        MessageInfo messageInfo = new MessageInfo();
        BeanUtil.copyProperties(mqttBody, messageInfo);
        //取得当前登陆人id
        messageInfo.setFromUserId(UserUtils.getUserDetailsDTO().getId());
        messageInfoService.save(messageInfo);
        //将messageInfo对象转换为json字符串
        String json = JSONUtil.toJsonStr(messageInfo);
        //发消息
        mqttGateway.sendToMqtt(json);

    }

    //对话发送方法
    public void sendToTopic(MqttBody mqttBody) {
        //取得当前登陆人id
        mqttBody.setFromUserId(UserUtils.getUserDetailsDTO().getUserInfoId());
        //创造一个主题为 发送者id+接收者id+默认聊天主题 的主题
        StringBuilder topic = new StringBuilder();
        topic.append(mqttBody.getFromUserId()).append(mqttBody.getReceiveUserId()).append(mqttConfig.getDefaultTopic());
        mqttBody.setTopic(topic.toString());
        //使用BeanUtils工具类将mqttBody转换为MessageInfo对象 并 保存消息到数据库
        MessageInfo messageInfo = new MessageInfo();
        BeanUtil.copyProperties(mqttBody, messageInfo);
        messageInfoService.save(messageInfo);
        //将messageInfo对象转换为json字符串
        String json = JSONUtil.toJsonStr(mqttBody);
        //发消息
        mqttGateway.sendToMqtt(json, topic.toString());
    }

    @Override
    public Result<?> getAllLoginUser() {

        //定义容器
        List<UserInfoDTO> userInfoDTOList = new ArrayList<>();
        //sayToken 拿到所有登录Token
        List<String> tokens = StpUtil.searchTokenValue("", 0, 10, true);
        //遍历tokens
        for (String token : tokens) {
            //拿到token对应的用户id
            Integer loginId = Integer.parseInt(StpUtil.getLoginIdByToken(token.split(":")[3]).toString());
            //得到用户信息
            UserInfoDTO userInfoById = userInfoService.getUserInfoById(loginId);
            //存入
            userInfoDTOList.add(userInfoById);
        }


        return Result.ok(
                MapUtil.builder(
                                new HashMap<String, Object>()
                        )
                        .put("userList", userInfoDTOList)
                        .put("total", userInfoDTOList.size())
                        .build()
        );
    }
}
